package com.itmake.sample.toolbox.word;

import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * word 转换成 html
 *
 * @author Amjacks
 * @since 2023/08/10
 */
public class WordUtil {

    private WordUtil() {}

    /**
     * 图片 base64 前缀
     */
    private static final String BASE64_IMAGE_PREFIX = "data:image/jpeg;base64,";

    /**
     * docx（2007版本word） 转换成 html
     *
     * @param docxIs docx 文件输入流
     * @return 转换成的 html 代码
     * @throws IOException 异常
     */
    public static String docxToHtml(InputStream docxIs) throws IOException {
        Map<String, String> image = new HashMap<>();
        // 转换参数设置
        XHTMLOptions options = XHTMLOptions.create();
        // 保存图片数据，并进行 base64 编码
        options.setExtractor((s, bytes) -> image.put(s, BASE64_IMAGE_PREFIX + Base64.getEncoder().encodeToString(bytes)));
        // 设置图片路径，这里替换为 base64 字符
        options.URIResolver(image::get);
        options.setIgnoreStylesIfUnused(false);
        options.setFragment(true);
        // 加载 word 文档生成 XWPFDocument对象
        XWPFDocument document = new XWPFDocument(docxIs);
        // 用于读取转换后的数据
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        // 转换 word
        XHTMLConverter.getInstance().convert(document, byteArrayOutputStream, options);
        String content = byteArrayOutputStream.toString();
        // 关闭流
        byteArrayOutputStream.close();
        return content;
    }

    /**
     * doc（2003版本word） 转换成 html
     *
     * @param docIs doc 文件输入流
     * @return 转换成的 html 代码
     * @throws IOException 异常
     */
    public static String docToHtml(InputStream docIs) throws IOException, ParserConfigurationException, TransformerException {
        // 构建文档对象
        HWPFDocument wordDocument = new HWPFDocument(docIs);
        WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
        // 保存图片数据，并进行 base64 编码
        wordToHtmlConverter.setPicturesManager((content, pictureType, suggestedName, widthInches, heightInches) ->
                BASE64_IMAGE_PREFIX + Base64.getEncoder().encodeToString(content));
        wordToHtmlConverter.processDocument(wordDocument);
        // 创建转换器
        Transformer serializer = TransformerFactory.newInstance().newTransformer();
        serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
        serializer.setOutputProperty(OutputKeys.INDENT, "yes");
        serializer.setOutputProperty(OutputKeys.METHOD, "html");
        // 用于读取转换后的数据
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        // 转换 word
        serializer.transform(new DOMSource(wordToHtmlConverter.getDocument()), new StreamResult(byteArrayOutputStream));
        // 关闭流
        byteArrayOutputStream.close();
        return byteArrayOutputStream.toString();
    }
}
